package com.zhang.testredisboot.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @Description Redis 消息监听器
 * @Author gongming.Zhang
 * @Date 2024/9/11 18:53
 * @Version 1.0
 */
/*
    当收到订阅的消息时，会将消息交给这个类处理。
     * 可以直接实现 MessageListener 接口，也可以继承它的实现类 MessageListenerAdapter.
     * 自动多线程处理，打印日志即可看出，即使手动延迟，也不会影响后面消息的接收。
 */
@Component
@Slf4j
public class RedisReceiveListener implements MessageListener {
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    /**
     * 处理回调逻辑。每次新消息到达时，都会调用此方法。通过 onMessage 方法执行业务代码
     * <p>
     * 该接口不仅可以访问实际消息，还可以访问接收消息的频道（Channel），以及订阅时用于匹配频道（Channel）的模式。
     * 此信息使被调用者不仅可以通过内容区分各种消息，还可以检查其他详细信息。
     *
     * @param message 消息对象，不能为 null
     * @param pattern 与通道匹配的模式（如果指定），可以为 null
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        // 1.获取消息所属的通道  -->  首先获取 字符串序列化器，再从给定的二进制数据中反序列化对象。
        String channel = redisTemplate.getStringSerializer().deserialize(message.getChannel());
        // 2.获取客户端发送的消息内容  -->  后期可以根据自己项目中 消息 的类型，来确定用什么序列化器
        Object msg = redisTemplate.getValueSerializer().deserialize(message.getBody());
        log.info("收到Redis订阅消息: channel={} msg={}", channel, msg);
    }
}
